package com.sghd.candy.module.player.manager;

import com.fasterxml.jackson.core.type.TypeReference;
import com.sghd.common.ramcache.anno.Inject;
import com.sghd.common.ramcache.service.EntityCacheService;
import com.sghd.common.utils.json.JsonUtils;
import org.springframework.stereotype.Component;

/**
 * @author Allen
 * @date 2018/12/07
 */
@Component
public class PlayerManager {
    @Inject
    private EntityCacheService<Long, Player> infoCache;
    @Inject
    private EntityCacheService<Long, PlayerOther> otherCache;

    public Player load(long playerId) {
        return infoCache.load(playerId);
    }

    public Player createPlayer(long playerId) {
        return infoCache.create(playerId, builder -> Player.valueOf(playerId));
    }

    public void addState(Player player, int state) {
        player.addState(state);
    }

    public void removeState(Player player, int state) {
        player.removeState(state);
    }

    public void setInfoCache(EntityCacheService<Long, Player> infoCache) {
        this.infoCache = infoCache;
    }

    public PlayerOther loadOther(long playerId) {
        return otherCache.loadOrCreate(playerId, builder -> PlayerOther.valueOf(playerId));
    }

    public void update(PlayerOther playerOther, String key, Object object) {
        if (object instanceof String) {
            playerOther.setContent(key, (String) object);
        } else {
            playerOther.setContent(key, JsonUtils.object2String(object));
        }
    }

    /**
     * 获取或者创建玩家辅助信息
     * @param owner 玩家标识
     * @param key 信息键值
     * @param clz 信息值类型
     * @return 不存在会返回null
     */
    public <T> T loadOther(long playerId, String key, Class<T> clz) {
        PlayerOther other = loadOther(playerId);
        return other.getContent(key, clz);
    }

    public <T> T loadOther(long playerId, String key, T defaultValue, Class<T> clz) {
        PlayerOther other = loadOther(playerId);
        T result = other.getContent(key, clz);
        if (result == null) {
            updateInfo(playerId, key, defaultValue);
            return defaultValue;
        }
        return result;
    }

    public <T> T loadOther(long playerId, String key, T defaultValue, TypeReference<T> typeReference) {
        PlayerOther other = loadOther(playerId);
        T result = other.getValue(key, typeReference);
        if (result == null) {
            updateInfo(playerId, key, defaultValue);
            return defaultValue;
        }
        return result;
    }

    public void updateInfo(long playerId, String key, Object value) {
        PlayerOther other = loadOther(playerId);
        String json = null;
        if (value instanceof String) {
            json = (String) value;
        } else {
            json = JsonUtils.object2String(value);
        }
        updateContent(other, key, json);
    }

    public void updateContent(PlayerOther info, String key, String content) {
        info.setContent(key, content);
    }
}
